package com.tuoyu.peopletest.view.ac;

import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.blankj.utilcode.util.KeyboardUtils;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
import com.stresscube.stresscubetest.ScanTest;
import com.stresscube.stresscubetest.TestCallback;
import com.tuoyu.peopletest.R;
import com.tuoyu.peopletest.entity.DataBean;
import com.tuoyu.peopletest.model.data.SaveAppData;
import com.tuoyu.peopletest.utils.SCLogUtils;
import com.tuoyu.peopletest.utils.SCTimeUtils;

import java.util.ArrayList;
import java.util.List;

public class ColloidalGoldActivity extends NomalBaseActivity implements TestCallback {
    static final String TAG = "Main";

    private static final int TEST_ITEM_COLLOIDAL_GOLD = 0;
    private static final int WAVE_LENGTH_365 = 0;
    private static final int WAVE_LENGTH_470 = 1;
    private static final int WAVE_LENGTH_525_40 = 2;
    private static final int WAVE_LENGTH_525_80 = 3;
    private static final boolean FLUORESCENCE_VALLEY = false;
    private static final boolean COLLOIDAL_GOLD_VALLEY = true;
    private static final int CODE_SCAN_RESULT = 1206;
//    USBDevicePDHIDWithAddress mDeviceHID = new USBDevicePDHIDWithAddress();
    ScanTest mScanTest;
    LineChart mLineChart;   //显示曲线
    TextView mtvMessage; //过程消息显示
    TextView mtvResult; //结果显示
    byte ledPosition = (byte) 0x03; //孔位为3
    byte mADPosition = (byte) 0x01; //AD孔位
    int mBrightness;
    boolean mbValley; //峰或谷
    ArrayList<Integer> mListResult = new ArrayList<Integer>(); //保存读出来的数据

    int miCalibrateBlack=0, miCalibrateWhite=0, miCalibrateGray=0;

    int mStart, mStop, mStep = 1;
    private double mArea1;
    private double mArea2;
    private int mWaveLength; //0-365 1-470 2-525.40 3-525.80
    private String waveLength;

    private EditText etNumber; //样品编号
    private RadioGroup rgTestItems; //测试项目
    private int mTestItem;

    private String mstrTestResult="";
    private String mScanStr;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    }

    @Override
    public void initContentView() {
        setContentView(R.layout.activity_colloidal_gold);

        InitData();
    }

    @Override
    public void initChildView() {

    }

    @Override
    protected void onStart() {
        super.onStart();
        mScanTest.init();
    }

    @Override
    protected void onStop() {
        super.onStop();
        mScanTest.release();
    }

    void InitData() {
        mScanTest=new ScanTest(this, this, true); //胶体金测试时，是吸收

        findViewById(R.id.v_et_main).setVisibility(View.VISIBLE);
        findViewById(R.id.v_main02).setVisibility(View.GONE);
        etNumber = findViewById(R.id.et_input);

        mtvMessage = findViewById(R.id.tvMessage);
        mtvResult = findViewById(R.id.tvResult);
        mLineChart = findViewById(R.id.lineChart_01);
        mListResult.clear();

        mScanStr = SaveAppData.getScanResult02();
        ((TextView)findViewById(R.id.tv_scan_result)).setText(mScanStr);
    }

    public void DisplayMessage(String msg) {
        mtvMessage.setText(msg + "\r\n" + mtvMessage.getText());
        Log.d(TAG, msg);
    }
    public void DisplayResult(String msg) {
        mtvResult.setText(msg + "\r\n" + mtvResult.getText());
        Log.d(TAG, msg);
    }

    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.tv_btn_scan:
                //扫码
                Intent scanIntent = new Intent(this, ScanActivity.class);
                startActivityForResult(scanIntent, CODE_SCAN_RESULT);
                break;
            case R.id.btnScanRead:
                findViewById(R.id.btnScanRead).setVisibility(View.INVISIBLE);
//                ScanRead();
                mListResult.clear();
                if(mScanTest.DoTest()) {
                    mStart = mScanTest.start;
                    mStop=mScanTest.stop;
                    mStep=mScanTest.step;
                    mBrightness=mScanTest.brightness;
                }
                break;
            case R.id.tv_btn_sure:
                //样本输入确定
                KeyboardUtils.hideSoftInput(this);
                findViewById(R.id.v_et_main).setVisibility(View.GONE);
                findViewById(R.id.v_main02).setVisibility(View.VISIBLE);

                mTestItem = TEST_ITEM_COLLOIDAL_GOLD;
                mWaveLength = WAVE_LENGTH_525_40;
                mBrightness = 600;
                mbValley = COLLOIDAL_GOLD_VALLEY;
                mStart = 5;//25;
                mStop = 100;//125;
                waveLength = "470";

                GetInput();
                break;
        }
    }

    private void GetInput() {
    }

    //计算峰值下的面积，一共2个峰，峰值左右各1mm，确定是向上的峰或向下的谷
    //左向外10个点及右向外10个点，取平均值，确定为基线
    int left = 10, right = 10, minGap = 50;//面积计算时，极值点左右的距离, minGap为两个峰值间的距离， 单位为0.1mm

    private void GetArea(int[] data, int step) {
        int max1 = 0, max2 = 0, max2Left = 0, max2Right = 0;
        int iMax1 = 0, iMax2 = 0;
        if (mbValley) {
            for (int iData = 0; iData < data.length; iData++) {
                data[iData] *= -1;
            }
            max2Left = max2Right = max1 = -256 * 256 * 256 * 127;
        }
        //找第1个峰
        for (int iData = 0; iData < data.length; iData++)
            if (data[iData] > max1) {
                max1 = data[iData];
                iMax1 = iData;
            }
        double area1 = CalcArea(data, iMax1, step);
        //找第2个峰
        int iMax2Left = 0, iMax2Right = 0;
        if (iMax1 * step > (left + right) + left) {
            for (int iData = left / step; iData < iMax1 - (left + right) / step; iData++)
                if (data[iData] > max2Left) {
                    max2Left = data[iData];
                    iMax2Left = iData;
                }
        }
        if ((data.length - iMax1) * step > (left + right) + right) {
            for (int iData = iMax1 + (left + right) / step; iData < data.length - right / step; iData++)
                if (data[iData] > max2Right) {
                    max2Right = data[iData];
                    iMax2Right = iData;
                }
        }
        if (max2Right > max2Left) {
            max2 = max2Right;
            iMax2 = iMax2Right;
        } else {
            max2 = max2Left;
            iMax2 = iMax2Left;
        }
        double area2 = CalcArea(data, iMax2, step);
        if (max2Right < max2Left) { //如果第2个峰在左边，则将area1和area2换位置
            double areax = area1;
            area1 = area2;
            area2 = areax;
        }
        mArea1 = area1;
        mArea2 = area2;
    }

//    boolean ReadCalibrationFromDevice() {
//        byte[] head=new byte[8];
//        byte[] data=new byte[12];
//        if(!mDeviceHID.ReadMemoBlock(0, head)) {
//            DisplayMessage("读数据头失败");
//            return false;
//        }
//        int ver=ConvertBytes2Int(head, 0);
//        int len=ConvertBytes2Int(head, 4);
//        if(ver!=0x0102||len!=12)
//            return false;
//        if(!mDeviceHID.ReadMemoBlock(8, data)) {
//            DisplayMessage("读数据失败");
//            return false;
//        }
//        int iBuffer=0;
//        miCalibrateBlack=ConvertBytes2Int(data, iBuffer);
//        iBuffer+=4;
//        miCalibrateWhite=ConvertBytes2Int(data, iBuffer);
//        iBuffer+=4;
//        miCalibrateGray=ConvertBytes2Int(data, iBuffer);
//        return true;
//    }
    private int ConvertBytes2Int(byte[] bytes, int iBuffer) {
        if(bytes==null||bytes.length<iBuffer+4)
            return -1;
        return (((bytes[iBuffer]&0xFF)*256+(bytes[iBuffer+1]&0xFF))*256+(bytes[iBuffer+2]&0xFF))*256+(bytes[iBuffer+3]&0xFF);
    }
    //给定点，算左右1mm的面积
    //首先计算左点外10个点和右点外10个点的平均值
    //再计算左右1mm内值减去平均值后的面积
    //A=-lgR/R0, R和R0分别为显色后的固相反射率和空白反射率
    //用白板和黑板将AD值归一转换成反射率R
    //再算每个点的吸光度A=-lgR
    //将1mm内的吸光度加起来得到积分吸光度，显示和保存这个数
    private double CalcArea(int[] data, int iMax, int step) {
        int average = 0;
        int nData = 0, sum = 0;
        for (int iData = iMax - left / step - 10; iData < iMax - left / step; iData++) {
            if (iData <= 0)
                continue;
            sum += data[iData];
            nData++;
        }
        for (int iData = iMax + right / step; iData < iMax + right / step + 10; iData++) {
            if (iData >= data.length)
                break;
            sum += data[iData];
            nData++;
        }
        if (nData == 0)
            return -1;
        average = sum / nData;
        double area = 0;
        for (int iData = iMax - left / step; iData < iMax + right / step; iData++) {
            if (iData < 0 || iData >= data.length) {
                Log.d("area", "Data index error:" + iData);
                continue;
            }
            area += GetAbsorbance(data[iData]);
        }
        area=((int)(area*1000+0.5))/1000.0;
        return area;
    }
    double GetAbsorbance(int data) {
        data*=-1;
        if(data<=miCalibrateBlack) return 0;
        if(miCalibrateWhite<=miCalibrateBlack) return 0;
        double R=(data-miCalibrateBlack)*1.0/(miCalibrateWhite-miCalibrateBlack);
        if(R>1)
            R=1;
        return -Math.log10(R);
    }
//    private boolean LEDOn() {
//        switch (mWaveLength) {
//            case 0:
//                return OpenLED365();
//            case 1:
//                return OpenLED470();
//            case 2:
//                return OpenLED525_1();
//            case 3:
//                return OpenLED525_2();
//            default:
//                return OpenLED470();
//        }
//    }

//    private boolean LEDOff() {
//        if (!mDeviceHID.LEDOn(ledPosition, (byte) 0x00, 0)) {
//            SendDispMessage("关灯失败");
//            return true;
//        }
//        SendDispMessage("关灯成功");
//        return true;
//    }

//    private boolean OpenLED(byte color) {
//        if (!mDeviceHID.LEDOn(ledPosition, color, mBrightness)) {
//            SendDispMessage("开灯失败");
//            return false;
//        }
//        SendDispMessage("开灯成功");
//        return true;
//    }

//    private boolean OpenLED365() {
//        return OpenLED((byte) 0x15);
//    }
//
//    private boolean OpenLED470() {
//        return OpenLED((byte) 0x2a);
//    }
//
//    private boolean OpenLED525_1() {
//        return OpenLED((byte) 0x40);
//    }
//
//    private boolean OpenLED525_2() {
//        return OpenLED((byte) 0x80);
//    }
//
//    private void ScanRead() {
//        if(!ReadCalibrationFromDevice()) {
//            Toast.makeText(this, "无校准数据，请先校准", Toast.LENGTH_LONG).show();
//            return;
//        }
//        new Test().start();
//    }

    void SendDispMessage(String str) {
        Message message = new Message();
        message.what = 1;
        message.obj = str;
        mHandler.sendMessage(message);
    }

    void SendDispData(int[] data) {
        Message message = new Message();
        message.what = 2;
        message.obj = data;
        mHandler.sendMessage(message);
    }

    void DispCurve() {
        Message message = new Message();
        message.what = 3;
        mHandler.sendMessage(message);
    }
    void SendDispData(int data) {
        Message message = new Message();
        message.what = 4;
        message.obj = data;
        mHandler.sendMessage(message);
    }

    void SendShowTestButton() {
        Message message = new Message();
        message.what = 5;
        mHandler.sendMessage(message);
    }
    void SendDispResult(String str) {
        Message message = new Message();
        message.what = 6;
        message.obj = str;
        mHandler.sendMessage(message);
    }

    @Override
    public void GotData(int data) {
        mListResult.add(data);
        DispCurve();
    }

    @Override
    public void GotData(int[] data) {

    }
    private int getPosition(int pos) {
        return mScanTest.start+pos/mScanTest.step;
    }
    private int getLeft(){
        return getPosition(mScanTest.peakLeft);
    }
    private int getRight(){
        return getPosition(mScanTest.peakRight);
    }

    @Override
    public void Notify(int status) {
        if(status==TestCallback.STATUS_TEST_SUCCESS) {
            String strMsg="测试完成: "+mScanTest.mArea1+"@"+getLeft()+" "+mScanTest.mArea2+"@"+getRight();
            SendDispMessage(strMsg);
        }else if(status==TestCallback.STATUS_TEST_FAIL)
            SendDispMessage("测试出错");
        else if(status==TestCallback.STATUS_TEST_START)
            SendDispMessage("开始测试");
        else if(status==TestCallback.STATUS_OPEN_LED_FAIL)
            SendDispMessage("开灯失败");
        else if(status==TestCallback.STATUS_MOVE_TRAY_TO_START_FAIL)
            SendDispMessage("移动到起点失败");
        else if(status==TestCallback.STATUS_TEST_FORCE_STOP)
            SendDispMessage("没有接收到停止信号，自动停止");
    }

//    class Test extends Thread {
//        @Override
//        public void run() { //改成发移动命令、连续获取AD、检测停止命令
//            do {
////                OpenLED470();
//                SendDispMessage("开始测试");
//                if (!mDeviceHID.MoveTray(0)) {
//                    SendDispMessage("失败，测试退出");
//                    break;
//                }
//                SendDispMessage("开灯");
//                if (!LEDOn()) break;
//                mListResult.clear();
//                SendDispMessage("移动到起点");
//                if (!mDeviceHID.MoveTray(mStart)) {
//                    SendDispMessage("失败，测试退出");
//                    break;
//                }
//                if (!mDeviceHID.StartADReceive(mADPosition)) break;
//                if (mDeviceHID.GetADAfterStart() < 0) break;
//                if (mDeviceHID.GetADAfterStart() < 0) break;
//                SendDispMessage("开始扫描");
//                if (!mDeviceHID.StartMoveTray(mStop)) {
//                    SendDispMessage("失败，测试退出");
//                    break;
//                }
//                while (true) { //连续读
//                    int data = mDeviceHID.GetADAfterStart();
//                    if (data <= 0) {
//                        if (!mDeviceHID.StopADReceive()) break;
//                        SendDispMessage("结束扫描");
//                        break;
//                    }
//                    mListResult.add(data);
//                    DispCurve();
//                }
//                if (!LEDOff()) break;
//                mDeviceHID.MoveTray(0);
//                SendDispMessage("结束测试");
//                super.run();
//
//                if (mListResult.size() > 10) {
//                    int[] datas = new int[mListResult.size()];
//                    for (int i = 0; i < mListResult.size(); i++)
//                        datas[i] = mListResult.get(i);
//                    GetArea(datas, mStep);
//                    CalcResult();
//                    SendDispResult("测试结果："+mstrTestResult+"\t样本号："+etNumber.getText().toString().trim()+" \tarea1:"+mArea1+"\tarea2:"+mArea2);
//                    //保存数据
//                    saveData();
//                }
//            }while(false);
//            SendShowTestButton();
//        }
//    }

//    private void CalcResult() {
//        switch (mTestItem) {
//            case TEST_ITEM_COLLOIDAL_GOLD:
//                CalcResultColloidalGold();
//                break;
//        }
//    }

    private void CalcResultColloidalGold() {
//        if (mArea1 < 0) return;
//        double y = Math.log10(mArea1);
//        double x = (y - 7.6567) / (-0.755);
//        double result = Math.pow(10, x);
//        if (result < 1)
//            mstrTestResult = "<1";
//        else if (result > 100)
//            mstrTestResult = ">100";
//        else
//            mstrTestResult = ((int) (result * 100)) / 100. + "";
//        int iDot=mstrTestResult.indexOf(".");
//        int nLen=mstrTestResult.length();
//        if(iDot<0)
//            mstrTestResult+=".00";
//        else if(iDot==nLen-2)
//            mstrTestResult+="0";
//        mstrTestResult+="nmol/L";
        mstrTestResult="积分吸光度:"+mArea1;
    }

    Handler mHandler = new Handler() {
        @Override
        public void handleMessage(@NonNull Message msg) {
            switch (msg.what) {
                case 1:
                    DisplayMessage((String) msg.obj);
                    break;
                case 2:
//                    DisplayData((int[]) msg.obj);
                    break;
                case 3:
                    DrawLineChart();
                    break;
                case 4:
                    DisplayMessage("AD: " + (int) msg.obj);
                    break;
                case 5:
                    findViewById(R.id.btnScanRead).setVisibility(View.VISIBLE);
                    break;
                case 6:
                    DisplayResult((String) msg.obj);
                    break;
            }
            super.handleMessage(msg);
        }
    };

    private void DrawLineChart() {
        if (mListResult == null || mListResult.size() <= 0) {
            Toast.makeText(this, "没有数据", Toast.LENGTH_LONG).show();
            return;
        }

        List<ILineDataSet> dataSets = new ArrayList<ILineDataSet>();
//        for (int fx = 0; fx < 10; fx++) {
//            if (!bF8ClearNIR[fx]) continue;
        List<Entry> entries = new ArrayList<Entry>();
//            for (int i = 0; i < mListResult.get(fx).size(); i++) {
//                entries.add(new Entry(mStart + i * mStep, mListResult.get(fx).get(i)));
//            }
        for (int i = 0; i < mListResult.size(); i++)
            entries.add(new Entry(mStart + i * 1.0f / mStep, mListResult.get(i)));
//            LineDataSet dataSet = new LineDataSet(entries, mstrWaveLength[fx]);
//        int color = GetColor(fx);
        LineDataSet dataSet = new LineDataSet(entries, "ad");
        int color = GetColor(0);
        dataSet.setColor(color);
        dataSet.setValueTextColor(color);
        dataSet.setCircleColor(color);
        dataSet.setCircleHoleColor(color);
        dataSet.setDrawCircles(false);
        dataSet.setDrawValues(false);
        dataSets.add(dataSet);
//        }
        LineData data = new LineData(dataSets);
        mLineChart.setData(data);
        mLineChart.invalidate(); // refresh
    }

    int[] colors = {Color.RED, Color.GREEN, Color.BLUE, Color.GRAY, Color.DKGRAY, Color.LTGRAY, Color.CYAN, Color.BLACK, Color.MAGENTA, Color.WHITE};

    private int GetColor(int i) {
        return colors[i % 10];
    }

    /**
     * 保存数据
     */
    private void saveData() {
        DataBean dataBean = new DataBean();
        dataBean.time = System.currentTimeMillis();
        //编号
        dataBean.number = etNumber.getText().toString().trim();
        dataBean.create_time = SCTimeUtils.getFormatData03(dataBean.time);

        dataBean.project = "";

        //两个面积
        dataBean.area1 = mArea1 + "";
        dataBean.area2 = mArea2 + "";
        dataBean.result = mstrTestResult;

        dataBean.ad = "0";
        dataBean.start = mStart + "";
        dataBean.stop = mStop + "";
        //步长
        dataBean.step = mStep + "";
        //波长
        dataBean.waveLength = waveLength;
        //亮度
        dataBean.brightness = mBrightness + "";

        if (mbValley) {
            //选择的是胶体金
            dataBean.jtj_or_yg = "1";
        } else {
            dataBean.jtj_or_yg = "2";
        }

        dataBean.save();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == CODE_SCAN_RESULT ) {
            if(resultCode == RESULT_OK){
                //扫码返回
                mScanStr = data.getStringExtra("data");
                SCLogUtils.e(TAG, "扫码返回=" + mScanStr);
                SaveAppData.setScanResult02(mScanStr);
                ((TextView)findViewById(R.id.tv_scan_result)).setText(mScanStr);
            }else {
                Toast.makeText(this,"扫码失败",Toast.LENGTH_SHORT).show();
            }

        }
    }
}